#include "dev_svc.h"
#include "drv_syscall.h"
#include <stdio.h>

#pragma GCC push_options
#pragma GCC optimize("O2")
ABS_USED
uint32_t Invoke_SVC_0(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
{
    CALL_SVC(0);
}

ABS_USED
uint32_t Invoke_SVC_1(uint32_t a)
{
    CALL_SVC(1);
}

uint32_t SVC_Call_0(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
{
    printf("SVC number = %u\n", 0);
    printf("SVC parameter 0 = %u\n", a);
    printf("SVC parameter 1 = %u\n", b);
    printf("SVC parameter 2 = %u\n", c);
    printf("SVC parameter 3 = %u\n", d);
    return 12;
}

uint32_t SVC_Call_1(uint32_t a)
{
    printf("SVC 1 arg = %u\n", a);
    return 13;
}

ABS_USED
uint32_t SVC_Callback(uint32_t *pwdSF)
{
    uint32_t svc_number;
    svc_number = ((char *)pwdSF[6])[-2];
    uint32_t ret;
    switch (svc_number) {
    case 0:
        ret = SVC_Call_0(pwdSF[0], pwdSF[1], pwdSF[2], pwdSF[3]);
        break;
    case 1:
        ret = SVC_Call_1(pwdSF[0]);
        break;
    default:
        break;
    }
    pwdSF[0] = ret;
    return 0;
}

void SVC_Handler(void)
{
    HANDLE_SP_EXCEPTION(SVC_Callback);
}
#pragma GCC pop_options

void HardFault_CallBack(uint32_t *pwdSF)
{
    unsigned int nextPoint1 = pwdSF[5];
    unsigned int nextPoint2 = pwdSF[6];
    unsigned int nextPoint3 = pwdSF[7];

    while (1) {
        static unsigned int i = 0;
        printf("<%s>[%d] SP = 0x%.8X, nextPoint = 0x%.8X / 0x%.8X / 0x%.8X\r\n",
               __func__, ++i, pwdSF, nextPoint1, nextPoint2, nextPoint3);
        for (int j = 0; j < 100000000; j++)
            ;
    }
}

void HardFault_Handler(void)
{
    HANDLE_SP_EXCEPTION(HardFault_CallBack);
}
